package com.itheima.service.impl;

import com.itheima.common.constant.MessageConstant;
import com.itheima.common.exception.DataNotFoundException;
import com.itheima.common.exception.FileDownloadFailException;
import com.itheima.common.exception.FileUploadFailedException;
import com.itheima.mapper.OrderSettingMapper;
import com.itheima.pojo.OrderSetting;
import com.itheima.pojo.OrderSettingVO;
import com.itheima.service.OrderSettingService;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderSettingServiceImpl implements OrderSettingService {

    @Autowired
    private OrderSettingMapper orderSettingMapper;

    /**
     * 下载文件
     *
     * @param filename
     * @param response
     */
    @Override
    public void download(String filename, HttpServletResponse response) {
        // 拼接文件路径
        String path = "templates\\" + filename;
        // 设置响应类型: excel
        response.setContentType("application/vnd.ms-excel");
        try (
                // 创建读取模板文件的输入流
                InputStream is = this.getClass().getClassLoader().getResourceAsStream(path);
                // 创建一个基于is的工作簿对象
                XSSFWorkbook workbook = new XSSFWorkbook(is);
                // 创建输出流
                ServletOutputStream os = response.getOutputStream();
        ) {
            // 将文件下载到客户端浏览器
            workbook.write(os);
        } catch (Exception e) {
            throw new FileDownloadFailException(MessageConstant.DOWNLOAD_FILE_FAIL);
        }
    }

    /**
     * 编辑预约人数
     *
     * @param orderSetting
     */
    @Override
    public void editNumberByOrderDate(OrderSetting orderSetting) {
        // 根据日期查询是否已经存在数据
        Integer count = orderSettingMapper.countByDate(orderSetting.getOrderDate());
        // 如果存在,则更新信息
        if (count > 0) {
            orderSettingMapper.update(orderSetting);
        } else {
            // 如果不存在.则新增信息
            orderSettingMapper.insertBatch(Collections.singletonList(orderSetting));
        }
    }

    /**
     * 根据日期查询预约设置信息
     *
     * @param date
     * @return
     */
    @Override
    public List<OrderSettingVO> getOrderSettingByMonth(String date) {
        List<OrderSetting> orderSettingList = null;
        try {
            // 解析日期,获取localDate类型的数据对象
            String[] dateStr = date.split("-");
            LocalDate firstDay = LocalDate.of(Integer.parseInt(dateStr[0]), Integer.parseInt(dateStr[1]), 1);
            // 获取本月的最后一天
            LocalDate endDay = LocalDate.of(Integer.parseInt(dateStr[0]), Integer.parseInt(dateStr[1]), firstDay.lengthOfMonth());
            // 查询范围日期内的预约设置信息
            orderSettingList = orderSettingMapper.selectByDate(firstDay, endDay);
        } catch (NumberFormatException e) {
            throw new DataNotFoundException(MessageConstant.GET_ORDERSETTING_FAIL);
        }
        // 判断查询结果是否为空
        if (orderSettingList == null || orderSettingList.isEmpty()) {
            return null;
        }
        // 将预约设置信息中的日期只保留日期封装到OrderSettingVO中
        List<OrderSettingVO> orderSettingVOList = new ArrayList<>();
        for (OrderSetting os : orderSettingList) {
            OrderSettingVO orderSettingVO = new OrderSettingVO(os.getOrderDate().getDayOfMonth(), os.getNumber(), os.getReservations());
            orderSettingVOList.add(orderSettingVO);
        }
        return orderSettingVOList;
    }

    /**
     * 上传文件 批量导入预约设置数据
     *
     * @param file
     */
    @Override
    public void upload(MultipartFile file) {
        try (
                // 获取上传文件的输入流
                InputStream is = file.getInputStream();
                // 根据输入流创建文件
                XSSFWorkbook excel = new XSSFWorkbook(is);
        ) {
            // 创建集合用来记录文件中的信息 key:日期  value:预约人数 自动去重
            Map<LocalDate, Integer> orderSettingMap = new HashMap<>();
            // 获取工作簿中的第一个工作表
            XSSFSheet sheet = excel.getSheetAt(0);
            // 创建 DataFormatter 对象来格式化单元格数据
            DataFormatter dataFormatter = new DataFormatter();
            // 遍历读取文件中的数据,存储到集合当中
            for (int i = 1; i <= sheet.getLastRowNum(); i++) {
                XSSFRow row = sheet.getRow(i);
                // 获取日期和人数信息
                String date = dataFormatter.formatCellValue(row.getCell(0));
                int number = (int) row.getCell(1).getNumericCellValue();
                // 如果人数小于等于0,则为无效数据,跳过
                if (date == null || number <= 0) {
                    continue;
                }
                // 将日期和预约人数封装到map对象中
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/M/d");
                LocalDate orderDate = LocalDate.parse(date, formatter);
                orderSettingMap.put(orderDate, number);
            }
            if (orderSettingMap.isEmpty()) {
                return;
            }
            // 将Map集合转换为List集合
            List<OrderSetting> orderSettingList = orderSettingMap.entrySet().stream()
                    .map(entry -> new OrderSetting(entry.getKey(), entry.getValue()))
                    .collect(Collectors.toList());
            // 获取map的key集合,批量删除日期集合中(可能)存在的数据
            Set<LocalDate> dateSet = orderSettingMap.keySet();
            orderSettingMapper.deleteByDates(dateSet);
            // 批量插入剩余的新数据
            orderSettingMapper.insertBatch(orderSettingList);
        } catch (Exception e) {
            throw new FileUploadFailedException(MessageConstant.IMPORT_ORDERSETTING_FAIL);
        }
    }
}
